package com.awesome.javademo.threads.lock.reentrantlock;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Author: zhangjingfang
 * Email:zhangjingfang@jeejio.com
 * Date: 2021/8/11 7:28 上午
 * Description:支付的所有账户
 */
public class Alipay {
    private double[] accounts;
    private Lock alipaylock;
    private Condition condition;

    public Alipay(int n, double money) {
        this.accounts = new double[n];
        alipaylock = new ReentrantLock();
        condition = alipaylock.newCondition();
        for (int i = 0; i < accounts.length; i++) {
            accounts[i] = money;
        }
    }

    /**
     * 这个结构确保只有一个线程可以进入临界区。
     * 把解锁放到finally很必要，一旦临界区有异常，锁必须要释放，否则其他线程永远被阻塞。
     * 在临界区，发现只有满足一个条件之后才能执行，可以舒勇条件对象来管理那些已经获得一把锁但却不能工作的线程。
     */
    public void baseUse() {
        Lock lock = new ReentrantLock();
        lock.lock();
        try {
            //...
        } finally {
            lock.unlock();
        }
    }

    /**
     * 一个锁对象可以拥有多个条件对象。
     * 可以用newCondition获得一个条件对象，调用条件对象的await，表示让前线程被阻塞并放弃锁。
     * 一旦线程调用await，就会进入该条件集并处于阻塞状态，知道另一线程调用signalAll方法为止,会重新激活因为这一条件而等待的线程。
     *
     * @param from
     * @param to
     * @param amount
     */
    public void transfer(int from, int to, int amount) {
        alipaylock.lock();
        try {
            while (accounts[from] < accounts[to]) {
                condition.await();
            }
            accounts[from] = accounts[from] - amount;
            accounts[to] = accounts[to] + amount;
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            alipaylock.unlock();
        }
    }

//    /**
//     * 等价于synchronized锁
//     *
//     * @param from
//     * @param to
//     * @param amount
//     */
//    public synchronized void transfer(int from, int to, int amount) {
//        alipaylock.lock();
//        try {
//            while (accounts[from] < accounts[to]) {
//                wait();
//            }
//            accounts[from] = accounts[from] - amount;
//            accounts[to] = accounts[to] + amount;
//            notifyAll();
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        } finally {
//            alipaylock.unlock();
//        }
//    }
}